/*
 * This file is part of John the Ripper password cracker,
 * Copyright (c) 1996-99,2003 by Solar Designer
 */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>

#include "logger.h"

void error(void)
{
#ifndef _JOHN_MISC_NO_LOG
	log_event("Terminating on error");
	log_done();
#endif

	exit(1);
}

void pexit(char *format, ...)
{
	va_list args;

	va_start(args, format);
	vfprintf(stderr, format, args);
	va_end(args);

	fprintf(stderr, ": %s\n", strerror(errno));

	error();
}

int write_loop(int fd, char *buffer, int count)
{
	int offset, block;

	offset = 0;
	while (count > 0) {
		block = write(fd, &buffer[offset], count);

/* If any write(2) fails, we consider that the entire write_loop() has
 * failed to do its job, unless we were interrupted by a signal. */
		if (block < 0) {
			if (errno == EINTR) continue;
			return block;
		}

		offset += block;
		count -= block;
	}

/* Should be equal to the requested size, unless our kernel got crazy. */
	return offset;
}

/* Read a line from stream */
char *fgetl(char *s, int size, FILE *stream)
{
	char *res, *pos;
	int c;

	/* Reads characters from stream and stores them as a C string into 
	   str until (num-1) characters have been read or either a newline 
	   or a the End-of-File is reached, whichever comes first. 
	   
	   A null character is automatically appended in str after the 
	   characters read to signal the end of the C string.*/
	if ((res = fgets(s, size, stream))) {
		/* On success, the function returns the same str parameter. */
		if (!*res) return res;

		/* Go to the end of the line */
		pos = res + strlen(res) - 1;

		/* if the line terminates with \n */
		if (*pos == '\n') {
			/* overwrite \n with NULL char */
			*pos = 0;
			if (pos > res)
			if (*--pos == '\r') *pos = 0;
		} else
		if ((c = getc(stream)) == '\n') {
			if (*pos == '\r') *pos = 0;
		} else
		while (c != EOF && c != '\n')
			c = getc(stream);
	}

	return res;
}

char *strnfcpy(char *dst, char *src, int size)
{
	char *dptr = dst, *sptr = src;
	int count = size;

	while (count--)
		if (!(*dptr++ = *sptr++)) break;

	return dst;
}

/* This function copies char by char from src pointer to 
   dst pointer with NULL termination. The coping process 
   ends either by reaching size variable or by terminating 
   with NULL in src pointer */
char *strnzcpy(char *dst, char *src, int size)
{
	char *dptr = dst, *sptr = src;
	int count = size;

	if (count)
		while (--count)
			/* Copy only if not NULL */
			if (!(*dptr++ = *sptr++)) break;
	*dptr = 0;

	return dst;
}

char *strnzcat(char *dst, char *src, int size)
{
	char *dptr = dst, *sptr = src;
	int count = size;

	if (count) {
		while (count && *dptr) {
			count--; dptr++;
		}
		if (count)
			while (--count)
				if (!(*dptr++ = *sptr++)) break;
	}
	*dptr = 0;

	return dst;
}

/* String pointer to lower case
   Ex: Options -> options */
char *strlwr(char *s)
{
	/* ASCII table represented in unsigned 0-255 */
	unsigned char *ptr = (unsigned char *)s;

	/* Traverse the string */
	while (*ptr)
	{
		/* In case you encounter capital letter */
		if (*ptr >= 'A' && *ptr <= 'Z')
			*ptr++ |= 0x20;	/* add 0x20 in ASCII table (for lowercase) */
	else
			ptr++;          /* Go to the next address */
	}

	return s;
}
